/* @(#)CoreImageManager.java
** 
** Copyright (C) 2001-2011 by Steven D. Stamps
**
**             Trademarks & Copyrights
** Flywheel Management Science(TM) and FlywheelMS(TM) are exclusive
** trademarks of Steven D. Stamps and may only be used freely for
** the purpose of identifying the unforked version of this software.
** Subsequent forks (if any) may not use these trademarks.  All other
** rights are reserved.
**
** DecKanGL (Decorated Kanban Glyph Language) and TribKn (Tribal Knowledge)
** are also exclusive trademarks of Steven D. Stamps.  These may be used
** freely within the unforked FlywheelMS application and documentation.
** All other rights are reserved.
**
** Trademark information is available at
** <http://www.flywheelms.org/trademarks>
**
** Flywheel Management Science(TM) is a copyrighted body of management
** metaphors, governance processes, and leadership techniques that is
** owned by Steven D. Stamps.  These copyrighted materials may be freely
** used, without alteration, by the community (users and developers)
** surrounding this GPL3-licensed software.  Additional copyright
** information is available at <http://www.flywheelms.org/copyrights>
**
**              GPL3 Software License
** This program is free software: you can use it, redistribute it and/or
** modify it under the terms of the GNU General Public License, version 3,
** as published by the Free Software Foundation. This program is distributed
** in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
** even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE.  See the GNU General Public License for more details. You should
** have received a copy of the GNU General Public License, in a file named
** COPYING, along with this program.  If you cannot find your copy, see
** <http://www.gnu.org/licenses/gpl-3.0.html>.
*/
package com.fmscorp.deckangl;

import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;

/*******************************************************************************
Factory class that returns an Image or ImageIcon given the URL or a
String path to the resource. Examples of valid Strings are:<br>
NETWORK<br>
- "http://hostname/somepath/somepic.jpg"<br>
- "http://hostname/somepath/somejar.jar/somepath/somepic.jpg<br>
LOCAL ABSOLUTE (from CLASSPATH)<br>
- "/somepath/somepic.jpg"<br>
- "/somepath/somejar.jar/somepath/somepic.jpg"<br>
LOCAL RELATIVE<br>
- "somepath/somepic.jpg"<br>
*******************************************************************************/
public class CoreImageManager {
	
 // for caching icons
  private static Map<URL, ImageIcon> iconCache;
  protected CoreImageManager() {}

  /**
   * Return a image created by drawing an arbitrary set of strings and images in
   * order. For example, this can be used to create right-aligned icons for a tabbed
   * pane by passing in a string as the first element of the patches array and an
   * icon image as the second element.
   */
  public static Image createPatchedImage(Component context, Object[] patches) {
    if ((context == null) ||
        (patches == null)) {
      return null;
    }

    BufferedImage dummyImage = new BufferedImage(0, 0, BufferedImage.TYPE_INT_ARGB);
    Graphics dummyGraphics = dummyImage.getGraphics();

    FontMetrics fontMetrics = context.getFontMetrics(context.getFont());
    int w = 0, h = 0;
    for (int i=0; i < patches.length; i++) {
      if (patches[i] instanceof String) {
        String patchString = (String) patches[i];
        Rectangle2D bounds = fontMetrics.getStringBounds(patchString, dummyGraphics);
        w += bounds.getWidth();
        h = Math.max(h, (int) bounds.getHeight());
      } else if (patches[i] instanceof Image) {
        Image patchImage = (Image) patches[i];
        w += patchImage.getWidth(context);
        h = Math.max(h, patchImage.getHeight(context));
      }
    }

    BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    Graphics g = bufferedImage.getGraphics();
    g.setFont(context.getFont());
    int offset = 0;
    for (int i=0; i < patches.length; i++) {
    	if (patches[i] instanceof String) {
    		String patchString = (String) patches[i];
    		Rectangle2D bounds = fontMetrics.getStringBounds(patchString, g);
        int verticalOffset = (h - (int) bounds.getHeight()) / 2;
        g.drawString(patchString, offset, verticalOffset);
      } else if (patches[i] instanceof Image) {
        Image patchImage = (Image) patches[i];
        int verticalOffset = (h - patchImage.getHeight(context)) / 2;
        g.drawImage(patchImage, offset, verticalOffset, context);
      }
    }

    return bufferedImage;
  }

  /****************************************************************************
  This is the method that does all the work for this class.
  All other methods either directly or indirectly call on this method to
  get an ImageIcon,
  either to return it or create and return an Image from it. Null is returned
  for an invalid URL parameter.
  ****************************************************************************/
  public static ImageIcon createImageIcon(URL iconUrl) {
    if(iconUrl == null) {
      return null;
    }

    if(iconCache == null) {
      iconCache = new HashMap<URL, ImageIcon>();
    }

    ImageIcon imageIcon = (ImageIcon)iconCache.get(iconUrl);
    if(imageIcon == null) {
      imageIcon = new ImageIcon(iconUrl);
      if(imageIcon.getIconHeight() < 0) { // valid ImageIcon not created
        return null;
      }
      iconCache.put(iconUrl, imageIcon);
    }
    return imageIcon;
  }

  /*****************************************************************************
   * uses resource loader : paths that start with "/" (note forward slash only *not* File.separator)
   * are relative to root of classpath, no leading slash means image is in the same directory as
   * this ImageManager (see getResouce javadocs for more info).
  *****************************************************************************/
  public static ImageIcon createImageIcon(String imagePath) {
    return CoreImageManager.createImageIcon(CoreImageManager.class.getResource(imagePath));
  }

  public static Image createImage(URL imageUrl) {
    return createImageIcon(imageUrl).getImage();
  }

  /*****************************************************************************
  Clear the icon cache.
  *****************************************************************************/
  public static void reset() {
    iconCache.clear();
    iconCache = null;
  }


}